\ Preprocessor FOOS demo - Copyright 2012 J.L. Bezemer
\ You can redistribute this file and/or modify it under
\ the terms of the GNU General Public License

\ Inspired by Mini-OOF, made by Bernd Paysan, 2008

[pragma] forcecellheap
include lib/ansmem.4th
include lib/termansi.4th
include 4pp/lib/foos.4pp

:: button                              ( addr --)
   class
     field: text                       \ address of text to be printed
     field: len                        \ legth of text to be printed
     field: x                          \ x-position on the screen
     field: y                          \ y-position on the screen
     method: init                      \ initialization method
     method: draw                      \ drawing method
   end-class {

     :static :draw ( addr --) {        \ define and init drawing method
       this -> x    @ this -> y   @ at-xy
       this -> text @ this -> len @ type
     } ; overrides draw

     :method ( a n addr -- ) {         \ define and init initialization method 
       0 this -> x    ! 0 this -> y    !
         this -> len  !   this -> text !
     } ; defines init
   }

   private{ text len }                 \ private declarations MUST be made
;                                      \ be right before the semi-colon

: reverse  text_reverse ;              \ some helper words for demonstrating
: normal   text_normal  ;              \ the overriding of a method

page                                   \ clear screen

static button foo                      \ define a static button
s" thin foo" foo => init               \ initialize the button
foo => draw                            \ now print it
                                       \ note the => which acts on methods
new button bar                         \ define a new button on the heap
s" fat bar" bar => init                \ initialize the button
1 bar -> y !                           \ change a property

:method { reverse this -> :draw normal } ; bar -> draw !
bar => draw cr                         \ override a method on an object
                                       \ and execute it
:: button+                             ( addr --)
   extends button                      \ make a derived class
     method: xy!                       \ add more methods
     method: coords?                   \ e.g. coordinate handling
   end-extends {                       \ initialize the new methods
                                       \ override method from supertype
     :method { reverse this -> :draw normal } ; defines draw
     :method { this -> y ! this -> x ! }      ; defines xy!
     :method { this -> x ? this -> y ? }      ; defines coords?
   }

   private{ x y }                      \ from here on, x and y are private!
;

new button+ foobar                     \ allocate a new object on the heap
s" foobar" foobar => init              \ initialize it (still works)
10 5 foobar => xy!                     \ set coordinates with new method
foobar => draw                         \ draw the button (as always)